package com.qf.utils;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

/**
 * @author 高圆圆
 * @date 2022/12/6 15:43
 * 加入Druid连接池的工具类
 *
 * 1)现在目的就创建数据源--javax.sql.DataSource接口--->通过DruidDataSourceFactory创建数据源
 * 2)模拟真实场景
 */
public class DruidJdbcUtils {

    //声明数据源
    private static DataSource ds  = null ;


    //模拟线程 :每一个线程使用自己的Conneciton
    private static ThreadLocal<Connection> t1 = new ThreadLocal<>();

    //构造方法私有化,外界类不能new
    private DruidJdbcUtils(){}

    //静态代码块
    static{
        try {
            //当前工具类一加载,读取src下面的druid.properties配置文件
            InputStream inputStream = DruidJdbcUtils.class.getClassLoader().
                    getResourceAsStream("druid.properties");
            //创建属性集合列表,将配置文件资源输入流加载属性集合列表中
            Properties prop = new Properties() ;

            prop.load(inputStream) ;
            System.out.println(prop);
            //通过DruidDataSourceFactory创建DataSource对象---->DruidDataSource具体子实现类
            ////给ds重写赋值
            ds = DruidDataSourceFactory.createDataSource(prop);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取数据源,就是将配置文件的内容加载到了DataSource
     * @return
     */
    public static DataSource getDataSource(){
        return ds ;
    }

    /**
     * 从连接池中获取连接对象  ---->首先需要创建DataSource接口对象
     * @return
     */
    public static Connection getConnection(){
        try {
            //1)从当前线程获取Conection
            Connection conn = t1.get();
            if(conn==null){
                //2)当前线程中没有连接对象
                //需要从DataSource连接池获取连接对象
                conn  = ds.getConnection();
                //3)将当前连接对象绑定在当前线程上
                t1.set(conn);
            }
            return conn ;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

        return  null ;
    }

    //释放资源 针对DQL语句
    public static void close(ResultSet rs, PreparedStatement ps ,Connection conn){
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(ps!=null){
            try {
                ps.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(conn!=null){
            try {
                conn.close(); //归还连接池中
                //需要从当前线程ThreadLocal进行解绑
                t1.remove();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }

    /**
     * 针对DDL或者DML语句
     * @param ps
     * @param conn
     */
    public static void close( PreparedStatement ps ,Connection conn){
       close(null,ps,conn);
    }

    //开启事务  ---控制事务:连接对象必须使用同一个!
    public static void setAutoCommit() throws SQLException {
        //从连接池获取连接对象
        Connection conn = getConnection();
        conn.setAutoCommit(false) ; //手动提交
    }

    //回滚事务
    public static void rollBackAndClose() throws SQLException {
        Connection conn = getConnection();
        conn.rollback(); //回滚
        conn.close();
        t1.remove(); //解绑
    }
    //提交事务
    public static void commitAndClose() throws SQLException {
        Connection conn = getConnection();
        conn.commit(); //提交事务
        conn.close();
        t1.remove(); //解绑
    }


    public static void main(String[] args) {
       // System.out.println(DruidJdbcUtils.getDataSource());
        System.out.println(DruidJdbcUtils.getConnection());
    }
}
